package service

import (
	"context"
	"encoding/json"
	"strings"
	"user-center/src/constant"
	"user-center/src/db"
	"user-center/src/model"
	"user-center/src/model/request"
	"user-center/src/model/response"
	"user-center/src/sdk/Ai"
	"user-center/src/utils"

	"github.com/go-redis/redis/v8"
	"github.com/gorilla/websocket"
	log "github.com/sirupsen/logrus"
)

func assemble(aicode *request.AiCode) string {
	return aicode.Description + "【【【" + aicode.Code + "】】】"
}

// DealWebsocketConn 循环
// 1 获取代码数据解析参数
// 2 发布频道/订阅频道
func AiCodeDealWebsocketConn(conn *websocket.Conn) {
	firstConn := false
	var pubsub *redis.PubSub
	ctx := context.Background()
	log.Info("ai code websocket connection ", conn.LocalAddr().Network())
	for {
		// 1 获取代码数据解析参数
		aiCode := &request.AiCode{}
		err := parseMessage(conn, aiCode)
		if err != nil {
			//关闭取消订阅
			break
		}
		// 2 订阅频道 首次连接只订阅频道
		if !firstConn {
			pubsub = redisPublish(ctx, 1, aiCode.GroupId+"aiCode", "", nil, conn)
			firstConn = true
			continue
		}
		// 推送自己到消息频道
		redisPublish(ctx, 2, aiCode.GroupId+"aiCode", aiCode, pubsub, conn)
		// 阻塞采用分布式锁确保同时只能有一个用户对ai提问
		lock := utils.NewRedisLock(db.RedisClient , context.Background() , "redis:lock:ai:code" , utils.DefaultExpireTime)
		lock.Lock()
		//组装请求发送给ai
		content := assemble(aiCode)
		res, err := Ai.DoSyncRequestContent(constant.Prompt, content)
		lock.UnLock()
		// log.Info("ai response :", res)
		if err != nil {
			continue
		}
		//将ai回复转成AiCodeRes
		res = res[strings.Index(res, "{") : strings.LastIndex(res, "}") + 1]
		log.Info("ai fix response :", res)
		aiCodeRes := &response.AiCodeResponse{}
		err = json.Unmarshal([]byte(res), aiCodeRes)
		if err != nil {
			continue
		}
		// ai给出了代码 推送到代码频道
		if aiCodeRes.Flag == 2 {
			code := &model.Code{
				Code: aiCodeRes.Code,
			}
			log.Info("success code" , code)
			redisPublish(ctx, 2, aiCode.GroupId, code, pubsub, conn)
		}
		clientRes := &request.AiCode{
			Response: aiCodeRes.Response,
		}
		// 推送ai回复到消息频道
		redisPublish(ctx, 2, aiCode.GroupId+"aiCode", clientRes, pubsub, conn)
	}

	pubsub.Unsubscribe(ctx)
	//退订所有订阅
	// pubsub.Close()
}
